home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GameStar 2004 April
/
Gamestar_61_2004-04_dvdb.iso
/
DVDStar
/
Editace
/
hltp.exe
/
{app}
/
Source Code
/
CZBindMaker
/
PrivateSettings
/
SettingContainer.cs
< prev
next >
Wrap
Text File
|
2003-10-10
|
18KB
|
675 lines
/*****************************************************************************
Copyright ⌐ 2003 by Martin Cook. All rights are reserved. If you like this
code then feel free to go ahead and use it. The only thing I ask is that
you don't remove or alter my copyright notice. Your use of this software
is entirely at your own risk. I make no claims or warrantees about the
reliability or fitness of this code for any particular purpose. If you
make changes or additions to this code please mark your code as being
yours. If you have questions or comments then please contact me at:
martinc@outdrs.net
Have Fun! :o)
*****************************************************************************/
using System;
using System.ComponentModel;
using System.Collections;
using System.IO;
using System.IO.IsolatedStorage;
using System.Xml;
using System.Xml.XPath;
using System.Text;
using System.Security;
using System.Security.Cryptography;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Design;
namespace PrivateSettings
{
/// <summary>
/// A persistant collection of runtime applications settings.
/// </summary>
[ToolboxBitmapAttribute(typeof(SettingContainer), "Images.SettingContainer.bmp")]
public class SettingContainer : System.ComponentModel.Component
{
// *******************************************************************
// Public delegates.
// *******************************************************************
/// <summary>
/// Signature for the SettingRead event handler.
/// </summary>
public delegate void SettingReadEventHandler(
object sender,
System.EventArgs e
);
/// <summary>
/// Signature for the SettingWrite event handler.
/// </summary>
public delegate void SettingWriteEventHandler(
object sender,
System.EventArgs e
);
// *******************************************************************
// Public events.
// *******************************************************************
[Description("Fired whenever the settings are read from storage.")]
public event SettingReadEventHandler SettingRead;
[Description("Fired before the settings are written to storage.")]
public event SettingWriteEventHandler SettingWrite;
// *******************************************************************
// Attributes.
// *******************************************************************
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// The collection of settings.
/// </summary>
private SettingCollection m_coll;
/// <summary>
/// The file to store settings into.
/// </summary>
private string m_fileName;
/// <summary>
/// Determines whether settings are stored into isolated storage.
/// </summary>
private bool m_isolatedStorageFlag;
/// <summary>
/// Determines whether settings are encrypted before they are stored.
/// </summary>
private bool m_encryptedStorageFlag;
/// <summary>
/// Used to encrypt/decrypt the settings.
/// </summary>
private static byte[] c_Key =
{
0x46,
0x98,
0x13,
0x04,
0x01,
0x99,
0x0A,
0x1D,
0x09,
0x10,
0x3C,
0x46,
0xF8,
0x01,
0x15,
0x12
};
/// <summary>
/// Used to encrypt/decrypt the settings.
/// </summary>
private static byte[] c_IV =
{
0x01,
0x42,
0xF3,
0x12,
0x05,
0xA6,
0x01,
0xD8,
0xA9,
0x17,
0x1F,
0x12,
0x1D,
0x14,
0xB5,
0x16
};
/// <summary>
/// Used to encrypt/decrypt the settings.
/// </summary>
private static RijndaelManaged c_csp = null;
// *******************************************************************
// Properties.
// *******************************************************************
/// <summary>
/// The collection of settings.
/// </summary>
[Description("The collection of settings."),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor(typeof(PrivateSettings.Design.SettingCollectionEditor),
typeof(UITypeEditor))]
public SettingCollection Settings
{
get {return m_coll;}
} // End Settings
// *******************************************************************
[Description("The file to store settings into.")]
public string FileName
{
get {return m_fileName;}
set {m_fileName = Path.GetFileName(value);}
} // End FileName
// *******************************************************************
[Description("Determines whether settings are stored into isolated storage.")]
public bool IsolatedStorage
{
get {return m_isolatedStorageFlag;}
set {m_isolatedStorageFlag = value;}
} // End IsolatedStorage
// *******************************************************************
[Description("Determines whether settings are encrypted before they are stored.")]
public bool EncryptedStorage
{
get {return m_encryptedStorageFlag;}
set {m_encryptedStorageFlag = value;}
} // End EncryptedStorage
// *******************************************************************
// Constructors.
// *******************************************************************
static SettingContainer()
{
c_csp = new RijndaelManaged();
c_csp.Key = c_Key;
c_csp.IV = c_IV;
} // End SettingContainer()
// *******************************************************************
public SettingContainer(System.ComponentModel.IContainer container)
{
container.Add(this);
InitializeComponent();
// Setup the default values for the attributes.
m_coll = new SettingCollection();
m_isolatedStorageFlag = false;
m_encryptedStorageFlag = true;
} // End SettingContainer()
// *******************************************************************
public SettingContainer()
{
InitializeComponent();
// Setup the default values for the attributes.
m_coll = new SettingCollection();
m_fileName = "settings.xml";
m_isolatedStorageFlag = false;
m_encryptedStorageFlag = true;
} // End SettingContainer()
// *******************************************************************
// Overrides.
// *******************************************************************
/// <summary>
/// A sorry excuse for a destructor.
/// </summary>
/// <param name="disposing">False if called by the runtime.</param>
protected override void Dispose(bool disposing)
{
// Should we cleanup our list?
if (disposing)
m_coll.Clear();
base.Dispose(disposing);
} // End Dispose()
// *******************************************************************
// Component Designer generated code.
// *******************************************************************
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
// *******************************************************************
// Public methods.
// *******************************************************************
public void Write()
{
Stream stream = null;
XmlTextWriter writer = null;
try
{
// Tell the world what is about to happen.
_FireSettingWrite();
// Where should we create the underlying file?
if (m_isolatedStorageFlag)
stream = new IsolatedStorageFileStream(
Path.GetFileName(m_fileName),
FileMode.Create, FileAccess.Write);
else
stream = File.Create(m_fileName);
// Create and configure the writer.
writer = new XmlTextWriter(stream, Encoding.UTF8);
writer.Formatting = Formatting.Indented;
// Start the underlying xml document.
writer.WriteStartDocument();
// Create the root element.
writer.WriteStartElement("settings");
// Loop and save the items.
foreach (Setting a in m_coll)
{
// Sanity check the storageKey before attempting to use it.
if (a.StorageKey.Length == 0)
throw new FormatException("missing storageKey attribute!");
// Create an element for the setting.
writer.WriteStartElement("setting");
// Write the storage key attribute for this element.
writer.WriteAttributeString("storageKey",
XmlConvert.EncodeName(a.StorageKey));
string currentValue;
// Should we use the current value or the default value?
if (a.CurrentValue.Length == 0)
currentValue = a.DefaultValue;
else
currentValue = a.CurrentValue;
// Should we encrypt the value?
if (m_encryptedStorageFlag == true)
currentValue = _Encrypt(currentValue);
// Write the value.
writer.WriteAttributeString("currentValue",
XmlConvert.EncodeName(currentValue));
// Finish the setting element.
writer.WriteEndElement();
} // End foreach item in the collection.
// Finish the root element.
writer.WriteEndElement();
// Finish the document.
writer.WriteEndDocument();
} // End try
finally
{
// Should we cleanup the writer?
if (writer != null)
{
writer.Flush();
writer.Close();
} // End if we should close the writer.
// Should we cleanup the stream?
if (stream != null)
{
// NOTE: the stream might have been closed
// when the writer was closed - so we ignore
// any errors.
try
{
stream.Flush();
stream.Close();
} // End try
catch (Exception)
{
} // End catch
} // End if we should close the stream.
} // End finally
} // End Write()
// *******************************************************************
public void Read()
{
Stream stream = null;
try
{
// Where should we open the underlying file?
if (m_isolatedStorageFlag)
stream = new IsolatedStorageFileStream(
Path.GetFileName(m_fileName),
FileMode.Open, FileAccess.Read);
else
stream = File.OpenRead(m_fileName);
// Attempt to open the document.
XPathDocument doc = new XPathDocument(stream);
// Create a navigator for the document.
XPathNavigator nav = doc.CreateNavigator();
// Select the list of setting nodes.
XPathNodeIterator iter = nav.Select("settings/setting");
// Loop through the nodes.
while (iter.MoveNext())
{
// Get the value of the attributes.
string storageKey = XmlConvert.DecodeName(
iter.Current.GetAttribute("storageKey", ""));
string currentValue = XmlConvert.DecodeName(
iter.Current.GetAttribute("currentValue", ""));
// Should we decrypt the value?
if (m_encryptedStorageFlag == true)
currentValue = _Decrypt(currentValue);
// Sanity check the storageKey before attempting to use it.
if (storageKey.Length == 0)
throw new FormatException("missing storageKey attribute!");
// TODO : look into replacing the ArrayList with a Hashtable...
// Loop through and find the right setting.
foreach (Setting a in m_coll)
{
// Did we find the right setting?
if (a.StorageKey == storageKey)
{
// Save the new current value.
a.CurrentValue = currentValue;
break;
} // End if we found the right setting.
} // End for each setting in the collection.
} // End while there are more setting nodes.
// Tell the world what happened.
_FireSettingRead();
} // End try
catch (FileNotFoundException)
{
// Getting here means that the settings file
// was not found. Which usually means that it
// hasn't been created yet. So, we iterate
// through all the settings and set their current
// values to whatever is configured for a default.
// Loop and configure each Setting
foreach (Setting a in m_coll)
a.CurrentValue = a.DefaultValue;
// Tell the world what happened.
_FireSettingRead();
} // End catch
finally
{
// Should we cleanup the stream?
if (stream != null)
{
// NOTE: the stream might have been closed
// when the document finished reading - so we ignore
// any errors.
try
{
stream.Flush();
stream.Close();
} // End try
catch (Exception)
{
} // End catch
} // End if we should close the stream.
} // End finally
} // End Read()
// *******************************************************************
// Private methods.
// *******************************************************************
/// <summary>
/// Fires the SettingRead event - checking first to to see if anyone
/// has subscribed to the event.
/// </summary>
private void _FireSettingRead()
{
// Don't fire events while in the designer.
if (this.DesignMode)
return;
// Fire the event if anyone is listening.
if (SettingRead != null)
SettingRead(this, System.EventArgs.Empty);
} // End _FireSettingRead()
// *******************************************************************
/// <summary>
/// Fires the SettingWrite event - checking first to to see if anyone
/// has subscribed to the event.
/// </summary>
private void _FireSettingWrite()
{
// Don't fire events while in the designer.
if (this.DesignMode)
return;
// Fire the event if anyone is listening.
if (SettingWrite != null)
SettingWrite(this, System.EventArgs.Empty);
} // End _FireOnSettingWrite()
// *******************************************************************
private string _Encrypt(string clearValue)
{
// Sanity check the parameter before attempting to use it.
if ((clearValue == null) || (clearValue.Length == 0))
return "";
ICryptoTransform cryptoTransform = null;
MemoryStream memoryStream = null;
CryptoStream cryptoStream = null;
try
{
// Convert the string into a byte array.
byte[] clearData = Encoding.Default.GetBytes(clearValue);
// Create the crypto transformer.
cryptoTransform = c_csp.CreateEncryptor();
// Create the crypto stream and the destination stream.
memoryStream = new MemoryStream();
cryptoStream = new CryptoStream(
memoryStream, cryptoTransform, CryptoStreamMode.Write);
// Write the data into the crypto (and memory) stream.
cryptoStream.Write(clearData, 0, clearData.Length);
cryptoStream.FlushFinalBlock();
// Seek to the beginning.
memoryStream.Position = 0;
// Copy the encrypted data to a buffer.
byte[] encryptedData = new byte[memoryStream.Length];
memoryStream.Read(encryptedData, 0, (int)memoryStream.Length);
// Encode the contents of the buffer.
string encryptedValue = Convert.ToBase64String(encryptedData);
// Return the encrypted value.
return encryptedValue;
} // End try
finally
{
// Should we close the crypto stream?
if (cryptoStream != null)
cryptoStream.Close();
// Should we close the memory stream?
if (memoryStream != null)
memoryStream.Close();
} // End finally
} // End _Encrypt()
// *******************************************************************
private string _Decrypt(string encryptedValue)
{
// Sanity check the parameter before attempting to use it.
if ((encryptedValue == null) || (encryptedValue.Length == 0))
return "";
ICryptoTransform cryptoTransform = null;
MemoryStream memoryStream = null;
CryptoStream cryptoStream = null;
try
{
// Decode the encrypted data.
byte[] encryptedData = Convert.FromBase64String(
encryptedValue);
// Create the crypto transformer.
cryptoTransform = c_csp.CreateDecryptor();
// Copy the encrypted data into a memory stream.
memoryStream = new MemoryStream(encryptedData, 0,
encryptedData.Length);
// Create the crypto stream.
cryptoStream = new CryptoStream(
memoryStream, cryptoTransform, CryptoStreamMode.Read);
// Copy the decrypted data to a buffer.
byte[] clearData = new byte[encryptedData.Length - 1];
cryptoStream.Read(clearData, 0, clearData.Length);
// Convert the data back into a string.
string clearValue = Encoding.Default.GetString(clearData);
// Test for trailing null characters.
int index = clearValue.IndexOf((char)0);
// Should we trim trailing nulls?
if (index != -1)
clearValue = clearValue.Substring(0, index);
// Return the decrypted value.
return clearValue;
} // End try
finally
{
// Should we close the crypto stream?
if (cryptoStream != null)
cryptoStream.Close();
// Should we close the memory stream?
if (memoryStream != null)
memoryStream.Close();
} // End finally
} // End _Decrypt()
// *******************************************************************
/// <summary>
/// If you remove this method, I'll come to your house late at night,
/// pull up all of your shrubberies, and kick your dog!
/// </summary>
private void _DoNothing() { }
} // End class SettingContainer
} // End namespace PrivateSettings